import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.withType
import org.jlleitschuh.gradle.ktlint.KtlintExtension
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType.CHECKSTYLE
import org.jlleitschuh.gradle.ktlint.tasks.GenerateReportsTask

/**
 * 插件名称
 */
const val KtlintPluginName = "org.jlleitschuh.gradle.ktlint"

/**
 * ktlint 版本，注意不是插件版本，而是 ktlint 版本
 */
const val KtlintVersion = "0.41.0"

/**
 * 用于控制是否在打包过程中开启 ktlint 代码格式检查的 property name ，可以通过 -PpropertyName 的方式注入
 */
const val KtlintPropertyName = "doKtlintCheck"

/**
 * 执行代码检查的 gradle task 的名字
 */
const val KtlintTaskName = "ktlintCheck"

fun Project.applyKtlint() {
    // editorconfig 文件位置
    val editorconfigFile = file("$rootDir/.editorconfig")
    // ktlint report 输出位置
    val ktlintReportLocation = project.layout.buildDirectory.dir("reportsOutputs")
    apply(plugin = KtlintPluginName)
    configure<KtlintExtension> {
        version.set(KtlintVersion)
        debug.set(true)
        verbose.set(true)
        android.set(true)
        outputToConsole.set(true)
        outputColorName.set("RED")
        // 发生了 格式错误的时候是否抛出异常
        ignoreFailures.set(false)
        enableExperimentalRules.set(true)
        // editorconfig 文件地址
        additionalEditorconfigFile.set(editorconfigFile)

        reporters {
            reporter(CHECKSTYLE)
        }
        filter {
            include { element ->
                val path: String = element.file.path
                path.contains("/src/") and path.endsWith(".kt")
            }
            exclude { element ->
                val path: String = element.file.path
                path.contains("/androidTest/") or path.contains("/test/")
            }
        }

        // 修改 report 的输出目录
        tasks.withType(GenerateReportsTask::class) {
            reportsOutputDirectory.set(ktlintReportLocation)
        }
        // 默认是要执行 ktlintcheck 任务的，如果不想执行，则将 ktlintcheck 设为 false
        // 不能用 ktlintCheck 作为变量名，因为这是一个 task 的名称，会抛出 类型转换异常
        val doKtlintCheck = findProperty(KtlintPropertyName)
        if (doKtlintCheck == "true" || doKtlintCheck == null) {
            afterEvaluate {
                tasks.findByName("preBuild")?.dependsOn(KtlintTaskName)
            }
        }
    }
}
